package com.pb.metadata.controller;

import com.pb.infra.oth.util.*;
import com.pb.metadata.service.DataSourceService;
import com.pb.infra.oth.entity.common.Page;
import com.pb.infra.oth.entity.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 数据源管理
 * @author liaohaoyuan
 * @date 20210301
 */
@Slf4j
@RestController
@RequestMapping("v1/metadata/dataSource")
public class DataSourceController {

    /**
     * 日志操作表
     */
    private static final String TABLE_NAME = "param_datasource";

    /**
     * 日志操作功能名
     */
    private static final String OPERATION_MENU = "数据源管理";

    /**
     * redis数据访问
     */
    @Resource
    private RedisUtil redisUtil;

    /**
     * 业务逻辑对象
     */
    @Resource
    private DataSourceService dataSourceService;

    /**
     * jwttoken配置类
     */
    @Resource
    private JwtTokenConfig jwtTokenConfig;

    /**
     * 查询数据源分页数据
     * @param paramMap 查询参数
     * @param page 页码
     * @return Result 返回数据
     */
    @GetMapping("select")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result select(@RequestParam Map<String, Object> paramMap, Page page) {
        return dataSourceService.select(paramMap, page);
    }

    /**
     * 查询应用标识
     * @return Result 返回数据
     */
    /*@GetMapping("getAppIdList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getAppIdList (@RequestParam Map<String,Object> paramMap, HttpServletRequest request){
        List<Map<String, Object>> appIdList = dataSourceService.getAppIdList(paramMap, request);
        return Result.ok(appIdList);
    }*/

    /**
     *获取数据源类型
     * @return Result 返回数据
     */
    @GetMapping("getDataSourceType")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getDataSourceType(){
        List<Map<String, Object>> dataSourceType = dataSourceService.getDataSourceType();
        return Result.ok(dataSourceType);
    }

    /**
     * 获取物理表类型
     * @return Result 返回数据
     */
    @GetMapping("getPhysicaTableTypeList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public List<Map<String,Object>> getPhysicaTableTypeList(@RequestParam Map<String,Object> paramMap){
        return dataSourceService.getPhysicaTableTypeList(paramMap);
    }

    /**
     * 获取数据源用途
     * @return Result 返回数据
     */
    @GetMapping("getDatasourceUse")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getDatasourceUse(){
        List<Map<String, Object>> datasourceUse = dataSourceService.getDatasourceUse();
        return Result.ok(datasourceUse);
    }

    /**
     * 获取数据库用户
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @GetMapping("getDatabaseUserList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getDatabaseUserList(@RequestParam Map<String,Object>paramMap){
        List<Map<String, Object>> databaseUserList = dataSourceService.getDatabaseUserList(paramMap);
        return Result.ok(databaseUserList);
    }

    /**
     * 数据源主表保存
     * @return Result 返回数据
     */
    @PostMapping("insert")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.ADD, menuName = OPERATION_MENU)
    public Result insert(@RequestBody Map<String,Object> paramMap, HttpServletRequest request){
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            paramMap.put("createTime",format.format(new Date()));
            Result insert = dataSourceService.insert(paramMap, request);
            return insert;
        }catch (Exception e){
            e.printStackTrace();
            return Result.error(Constant.EXIST, Constant.INSERT_ERROR_MSG);
        }
    }

    /**
     * 数据源修改
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("update")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result update(@RequestBody Map<String,Object> paramMap, HttpServletRequest request){
        String databaseObjectName=(String)paramMap.get("databaseObjectName");
        paramMap.put("databaseObjectName",databaseObjectName.toUpperCase());
        return dataSourceService.update(paramMap, request);
    }

    /**
     * 数据源删除
     * @return Result 返回数据
     */
    @PostMapping("deleteBatch")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.DEL, menuName = OPERATION_MENU)
    public Result deleteBatch(@RequestBody List<String> list){
        dataSourceService.deleteBatch(list);
        return Result.OK_EMPTY;
    }

    /**
     * 启用OR停用
     * @param list 请求参数
     * @return Result 返回数据
     */
    @PostMapping("startOrStop")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result startOrStop(@RequestBody List<Map<String,Object>> list){
        dataSourceService.startOrStop(list);
        return Result.OK_EMPTY;
    }

    /**
     * 锁定OR提交
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("lockouts")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public  Result lockouts(@RequestBody Map<String,Object> paramMap){
        dataSourceService.lockouts(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 同步 把数据源添加的字段初始化
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("synchronismData")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result synchronismData(@RequestBody Map<String,Object> paramMap, HttpServletRequest request){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        paramMap.put("Time",format.format(new Date()));
        dataSourceService.synchronismData(paramMap, request);
        return Result.OK_EMPTY;
    }

    /**
     * 获取配置表左表数据
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @GetMapping("getLeftTableData")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getLeftTableData(@RequestParam Map<String, Object> paramMap){
        return dataSourceService.getLeftTableData(paramMap);
    }

    /**
     * 获取字段类型
     * @return Result 返回数据
     */
    @GetMapping("getFieldTypeDatas")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getFieldTypeDatas(){
        List<Map<String, Object>> fieldTypeDatas = dataSourceService.getFieldTypeDatas();
        return Result.ok(fieldTypeDatas);
    }

    /**
     * 获取配置表右表数据
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @GetMapping("getRightTableData")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getRightTableData(@RequestParam Map<String,Object> paramMap){
        List<Map<String, Object>> rightTableData = dataSourceService.getRightTableData(paramMap);
        return Result.ok(rightTableData);
    }

    /**
     * 保存配置表右表数据
     * @param list 请求参数
     * @return Result 返回数据
     */
    @PostMapping("saveTables")
    @SysLog(tableName = "param_datasource_column", action = Constant.ACTION_NAME.ADD, menuName = OPERATION_MENU)
    public Result saveTables(@RequestBody List<Map<String,Object>> list, HttpServletRequest request) {
        dataSourceService.saveTables(list, request);
        return Result.OK_EMPTY;
    }

    /**
     * 导出
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("/leadingOuts")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.EXP, menuName = OPERATION_MENU)
    public Map<String, Object> leadingOuts(@RequestBody Map<String,Object> paramMap, HttpServletRequest request) {
        String token = request.getHeader(jwtTokenConfig.getHeader());
        List<Map<String,Object>> Data = (List<Map<String,Object>>) paramMap.get("Data");
        if (Data.size()>0) {
            paramMap.put("Data",Data);
        } else {
            paramMap.put("Data",null);
        }
        List<Map<String,Object>> list = dataSourceService.getLeadingOutsData(paramMap);
        List<Map<String,Object>> datasourceList=new ArrayList<Map<String, Object>>();
        for (Map<String, Object> map : list) {
            Map<String,Object> datasourceMap=new HashMap<String,Object>();
            datasourceMap.put("DatasourceId",map.get("DATASOURCE_ID"));
            datasourceList.add(datasourceMap);
        }
        List<Map<String, Object>> paramDatasourcelist=new ArrayList<>();
        double ceil1 =datasourceList.size()!=0? Math.floor(datasourceList.size() / 500):0.0;
        if (datasourceList.size()%500!=0){
            ceil1+=1;
        }
        for (int i = 1; i <=ceil1 ; i++) {
            int end=0;
            if ((i*500)>datasourceList.size()){
                end=datasourceList.size();
            }else {
                end=i*500;
            }
            paramMap.put("Data",datasourceList.subList((i-1)*500,end));
            paramDatasourcelist.addAll(dataSourceService.getParamDatasourceColumn(paramMap));
        }
        List<Map<String,Object>> data =datasourceList.size()>0?paramDatasourcelist:new ArrayList<Map<String,Object>>();
        //List<Map<String, Object>> appIdList = dataSourceService.getAppIdList(paramMap, request);
        List<Map<String, Object>> databaseUserList = dataSourceService.getDatabaseUserList(paramMap);
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder databaseUserBuffer = new StringBuilder();
        StringBuilder datasourCedeBuffer = new StringBuilder();
        StringBuilder datasourceUseBuffer = new StringBuilder();
        StringBuilder physicaTableBuffer = new StringBuilder();
        String physicaTableTypeStr = (String)redisUtil.get("physicaTableTypeStr");
        if (physicaTableTypeStr!=null && !"".equals(physicaTableTypeStr)){
            physicaTableBuffer.append(physicaTableTypeStr);
        }else {
            List<Map<String, Object>> physicaTableTypeList = dataSourceService.getPhysicaTableTypeList(paramMap);
            physicaTableBuffer.append("物理表类型:");
            for (int i = 0; i < physicaTableTypeList.size(); i++) {
                Map<String, Object> map = physicaTableTypeList.get(i);
                physicaTableBuffer.append("- "+map.get("CODE"));
                if(i!= physicaTableTypeList.size()-1){
                    physicaTableBuffer.append(", ");
                }
            }
            redisUtil.set("physicaTableTypeStr",physicaTableBuffer.toString(),86400);
        }
        /*stringBuilder.append("应用名称： ");
        for (int i = 0; i < appIdList.size(); i++) {
            Map<String,Object> map=appIdList.get(i);
            stringBuilder.append("- "+map.get("CNAME"));
            if (i!=appIdList.size()){
                stringBuilder.append(", ");
            }
        }*/
        databaseUserBuffer.append("数据库用户：");
        for (int i = 0; i < databaseUserList.size(); i++) {
            Map<String,Object> map=databaseUserList.get(i);
            databaseUserBuffer.append("- "+map.get("CNAME"));
            if (i!=databaseUserList.size()-1){
                databaseUserBuffer.append(", ");
            }
        }
        String dataSourceTypeStr = (String)redisUtil.get("dataSourceTypeStr");
        if(dataSourceTypeStr != null && !"".equals(dataSourceTypeStr)){
            datasourCedeBuffer.append(dataSourceTypeStr);
        }else {
            List<Map<String, Object>> dataSourceType = dataSourceService.getDataSourceType();
            datasourCedeBuffer.append("数据源类型：");
            for (int i = 0; i < dataSourceType.size(); i++) {
                Map<String,Object> map=dataSourceType.get(i);
                datasourCedeBuffer.append("- "+map.get("CNAME"));
                if (i!= dataSourceType.size()-1){
                    datasourCedeBuffer.append(", ");
                }
            }
            redisUtil.set("dataSourceTypeStr",datasourCedeBuffer.toString(),86400);
        }
        String datasourceUseStr = (String)redisUtil.get("dataSourceTypeStr");
        if(datasourceUseStr != null && !"".equals(datasourceUseStr)){
            datasourceUseBuffer.append(datasourceUseStr);
        }else {
            List<Map<String, Object>> datasourceUse = dataSourceService.getDatasourceUse();
            datasourceUseBuffer.append("数据源用途：");
            for (int i = 0; i < datasourceUse.size(); i++) {
                Map<String,Object> map=datasourceUse.get(i);
                datasourceUseBuffer.append("- "+map.get("CNAME"));
                if(i!=datasourceUse.size()){
                    datasourceUseBuffer.append(", ");
                }
            }
            redisUtil.set("datasourceUseStr",datasourceUseBuffer.toString(),86400);
        }
        paramMap.clear();
        String[][] strArr = {{"数据库名称","数据库用户","数据库用户对象","中文名称","数据源类型","物理表类型","数据源用途","有效标识","排序标识","备注"},
                {"数据库名称","数据库用户","对象名称","字段序号","字段名称","源字段名称","源字段类型","中文名称","主键标识","可空标识","业务键标识","描述标识","维度标识","度量标识","分区键标识"}};
        String[][] nameArr ={{"DATABASENAME","DATABASEUSER","DATABASEOBJECTNAME","CNNAME","DATASOURCEDESC","PHYSICATABLETYPE","DATASOURCEUSEDESC","ACTIVEDESC","ORDERFLAG","REMARKS"},
                {"DATABASENAME","DATABASE_USER","DATABASE_OBJECT_NAME","COLUMN_NO","COLUMN_NAME","SOURCE_COLUMN_NAME","SOURCE_COLUMN_TYPE","CN_NAME","PK_FLAG","NULL_FLAG","BK_FLAG","REMARK_FLAG","DIMENSION_FLAG","METRIC_FLAG","PATITION_KEY_FLAG"}};
        String[][] dataType = {{"STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING"},
                {"STRING","STRING","STRING","NUMBER","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING"}};
        String[][] comments  = {{"",databaseUserBuffer.toString(),"","",datasourCedeBuffer.toString(),physicaTableBuffer.toString(),datasourceUseBuffer.toString(),"有效标识：-启用，-停用","",""},
                {"",databaseUserBuffer.toString(),"","","","","","","主键标识：1 -是，0 -否","可空标识：1 -是，0 -否","业务键标识：1 -是，0 -否","描述标识：1 -是，0 -否","维度标识：1 -是，0 -否","度量标识：1 -是，0 -否","分区键标识：1 -是，0 -否"}};
        Object[] obj = {list,data};
        String[] jobBookName={"数据源","配置表"};
        paramMap.put("jobBookName",jobBookName);//工作薄名称
        paramMap.put("title",strArr);//表头的列名
        paramMap.put("order",nameArr);//每个字段的名称
        paramMap.put("comments",comments);//需要添加的批注
        paramMap.put("data",obj);//需要导出的数据
        paramMap.put("dataType",dataType);//数据类型 有NUMBER,STRING,DOUBLE三种数据类型
        paramMap.put("fileName","数据源管理");
        paramMap.put("token",token); // token
        return  paramMap;
    }

    /**
     * 导入
     * 加入@ImportExcel注解完成数据的校验过程
     * @param paramMap 获取校验完成的数据（data），及提示信息(msg)和状态(caode)，code=1表示正确，code=-1表示数据不正确
     * @return Result 返回数据
     */
    @PostMapping("importExcel")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.IMP, menuName = OPERATION_MENU)
    public Result importExcel(@ImportExcel() Map<String,Object> paramMap){
        try {
            List<List<Map<String,Object>>> data = ( List<List<Map<String,Object>>>) paramMap.get("data"); //得到Excel中的所有数据
            Integer code = (Integer) paramMap.get("code");
            if (code!=-1){
                String msg = dataSourceService.importExcel(data);
                if (!"".equals(msg)){
                    paramMap.put("msg",msg+paramMap.get("msg"));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            paramMap.put("msg","导入遇到异常请联系管理员");
        }
        paramMap.remove("data");
        return Result.ok(paramMap);
    }

    /**
     * 删除配置表数据
     * @param list 请求参数
     * @return Result 返回数据
     */
    @PostMapping("daleteTableData")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.DEL, menuName = OPERATION_MENU)
    public Result daleteTableData(@RequestBody List<String> list){
       try {
           dataSourceService.daleteTableData(list);
       }catch (Exception e){
           return Result.error("400","无法完成删除,"+e.getCause().toString().split(":")[2]);
       }
        return Result.OK_EMPTY;
    }
}
